﻿using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace CC_NSISrunner
{
    class Program
    {
        private static NsisXmlFormatter xmlFormatter;
        private static TextWriter textWriter;
        private static bool testMode = false;

        /// <summary>
        /// The specified args.
        /// 0 - NSIS full path
        /// 1 - full path to NSI
        /// 3 - full output xml path
        /// or
        /// 0 - -t
        /// 1 - test output from NSIS
        /// 3 - full output xml path
        /// </summary>
        /// <param name="args">The args.</param>
        static int Main(string[] args)
        {
            int exitCode = 1;
            if (args == null || args.Length < 3)
            {
                string appName = System.IO.Path.GetFileName(Assembly.GetEntryAssembly().CodeBase);
                Console.WriteLine("Usage:");
                Console.WriteLine("\t {0} 'path to makensis.exe' 'path to project.nsi' 'output.xml' [nsi additional options]", appName);
                return exitCode;
            }
            string inputTextFileName = string.Empty;
            string nsisApplicationPath = "";

            string xmlFileName = args[2];
            xmlFormatter = new NsisXmlFormatter(xmlFileName);

            if (args[0].ToLower() == "-t")
            {
                inputTextFileName = args[1];
                testMode = true;
            }
            else
            {
                // Application path and command line arguments
                nsisApplicationPath = args[0];
            }

            if (!testMode)
            {
                string txtFileName = ReplaceExtension(xmlFileName, ".txt");

                // create a writer and open the file
                textWriter = new StreamWriter(txtFileName);

                string nsisApplicationArguments = "";
                for (int i = 3; i < args.Length; i++)
                {
                    nsisApplicationArguments += " " + args[i];
                }
                if (!String.IsNullOrEmpty(nsisApplicationArguments))
                {
                    nsisApplicationArguments += " ";
                }

                // call of nsis script must be the last one
                nsisApplicationArguments += "\"" + args[1] + "\"";

                // Create a new process object
                Process nsisProcess = new Process();

                // StartInfo contains the startup information of
                // the new process
                nsisProcess.StartInfo.FileName = nsisApplicationPath;
                nsisProcess.StartInfo.Arguments = nsisApplicationArguments;

                // These two optional flags (UseShellExecute,CreateNoWindow) ensure that no DOS window appears
                nsisProcess.StartInfo.UseShellExecute = false;
                nsisProcess.StartInfo.CreateNoWindow = true;

                // If this option is set the DOS window appears again :-/
                // ProcessObj.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

                // This ensures that you get the output from the DOS application
                nsisProcess.StartInfo.RedirectStandardOutput = true;
                nsisProcess.StartInfo.RedirectStandardError = true;

                nsisProcess.OutputDataReceived += nsisProcess_OutputDataReceived;
                nsisProcess.ErrorDataReceived += nsisProcess_ErrorDataReceived;
                try
                {
                    // Start the process
                    nsisProcess.Start();

                    // Start the asynchronous read of the sort output stream.
                    // Must be after process start
                    nsisProcess.BeginOutputReadLine();
                    nsisProcess.BeginErrorReadLine();


                    // Wait that the process exits
                    nsisProcess.WaitForExit();

                    // set EOF
                    xmlFormatter.ParseInput(null);

                    // Now read the output of the DOS application
                    if (nsisProcess.StartInfo.RedirectStandardOutput)
                    {
                        //string result = nsisProcess.StandardOutput.ReadToEnd();
                        //Console.Write(result);
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine("Exception:\n" + exception.Message);

                }
                finally
                {
                    exitCode = nsisProcess.ExitCode;

                    //// close the stream
                    if (textWriter != null)
                    {
                        textWriter.Close();
                    }
                }
            }
            else
            {
                //test mode
                // create reader & open file
                TextReader textReader = new StreamReader(inputTextFileName);
                string line;
                while ((line = textReader.ReadLine()) != null)
                {
                    ProcessNsisString(line);
                }
                // set EOF
                xmlFormatter.ParseInput(null);
                textReader.Close();
            }
            return exitCode;
        }

        private static string ReplaceExtension(string xmlFileName,string extension)
        {
            return Path.GetDirectoryName(xmlFileName) +
                   Path.AltDirectorySeparatorChar +
                   Path.GetFileNameWithoutExtension(xmlFileName) +
                   extension;
        }

        static void nsisProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (textWriter != null)
            {
                textWriter.Write("*E*" + e.Data);
            }
            Console.WriteLine("*E*" + e.Data);
            xmlFormatter.SetErrorState();
        }

        static void nsisProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            ProcessNsisString(e.Data);
            //throw new NotImplementedException();
        }

        private static void ProcessNsisString(string line)
        {
            if (textWriter != null)
            {
                textWriter.WriteLine(line);
            }
            Console.WriteLine(line);
            xmlFormatter.ParseInput(line);
        }
    }
}
